package jp.gr.java_conf.genzo.wifinotify;

import jp.gr.java_conf.genzo.wifinotify.data.LogTracker;
import jp.gr.java_conf.genzo.wifinotify.util.LocationUtil;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.IBinder;
import android.os.Message;
import android.widget.Toast;

public class NotifyService extends Service implements Callback {

    @SuppressWarnings("unused")
    private static final String TAG = NotifyService.class.getSimpleName();

    static final String INTENT_NOTIFY_KEY = "notify";
    static final String NOTIFY_ON = "notify_on";
    static final String NOTIFY_OFF = "notify_off";

    static final String INTENT_WIFI_INFO_KEY = "wifi_info";
    static final String INTENT_NETWORK_INFO_KEY = "network_info";

    static final int NOTIFICATION_ID = 141421356;

    static final int END_SERVICE = 17320507;

    private Handler mHandler = null;

    @Override
    public boolean handleMessage(Message arg0) {
        if (arg0.what == END_SERVICE) {
            stopSelf();
        }
        return false;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        mHandler = new Handler(this);
    }

    private void postFinish() {
        mHandler.removeMessages(END_SERVICE);
        mHandler.sendEmptyMessageDelayed(END_SERVICE, 10 * 60 * 1000);
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent == null) {
            return super.onStartCommand(intent, flags, startId);
        }

        // プレファレンスより、設定を取得する
        AppSettings as = new AppSettings(this);
        NetworkInfo ni = intent.getParcelableExtra(INTENT_NETWORK_INFO_KEY);
        WifiInfo wi = intent.getParcelableExtra(INTENT_WIFI_INFO_KEY);

        String operation = intent.getStringExtra(INTENT_NOTIFY_KEY);

        if (operation.equals(NOTIFY_OFF)) {
            clearNotification(as, ni, wi);
            postFinish();
        } else {
            // 通知系処理を行う
            if (as.isNotification()) {
                doNotification(as, ni, wi);
            }

            // 位置情報を保存する
            putLog(as, ni, wi);
        }

        return super.onStartCommand(intent, flags, startId);
    }

    private void clearNotification(AppSettings as, NetworkInfo ni, WifiInfo wi) {
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        manager.cancelAll();

    }

    private void putLog(final AppSettings as, final NetworkInfo ni,
            final WifiInfo wi) {

        final long curTime = System.currentTimeMillis();
        LocationListener listener = new LocationListener() {
            @Override
            public void onLocationChanged(Location loc) {

                Object[] args = new Object[] { wi.getSSID(), wi.getRssi(),
                        loc.getLatitude(), loc.getLongitude(),
                        loc.getAccuracy(), curTime, };

                LogTracker lt = new LogTracker();
                try {
                    lt.insert(args);
                } finally {
                    lt.close();
                }

                LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
                lm.removeUpdates(this);
                postFinish();
            }

            @Override
            public void onProviderDisabled(String provider) {
            }

            @Override
            public void onProviderEnabled(String provider) {
            }

            @Override
            public void onStatusChanged(String provider, int status,
                    Bundle extras) {
            }
        };

        LocationUtil.getLoaction(listener);

    }

    private void doNotification(AppSettings as, NetworkInfo ni, WifiInfo wi) {
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        int icon = R.drawable.ic_stat_notify;
        String title = getString(R.string.notify_title);
        long when = System.currentTimeMillis();

        Notification notification = new Notification(icon, title, when);

        // 音
        String sound = as.getNotifyRingtone();
        if (sound != null) {
            notification.sound = Uri.parse(sound);
        }

        // バイブ
        if (as.isNotifyVibrator()) {
            notification.vibrate = new long[] { 0, 1000, 100, 1000, 100, 1000 };
        }

        // LED
        if (as.isNotifyLED()) {
            notification.flags |= Notification.FLAG_SHOW_LIGHTS;
            notification.ledARGB = 0xff00ff00;
            notification.ledOnMS = 200;
            notification.ledOffMS = 1000;
        }

        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        int ipAddress = wi.getIpAddress();
        String ip = ((ipAddress >> 0) & 0xFF) + "."
                + ((ipAddress >> 8) & 0xFF) + "."
                + ((ipAddress >> 16) & 0xFF) + "."
                + ((ipAddress >> 24) & 0xFF);
        String text = String.format(getString(R.string.notify_message),
                wi.getSSID(), ip, wi.getRssi());

        Intent intent = new Intent(this, WifiNotifyActivity.class);
        intent.putExtra("SSID", wi.getSSID());
        intent.putExtra("NEXT_CLASS", LogMapActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
        notification.setLatestEventInfo(this, title, text, pi);

        manager.notify(NOTIFICATION_ID, notification);

        // TOAST
        if (as.isToast()) {
            showToast(as, text);
        }

    }

    private void showToast(AppSettings as, String text) {
        if (as.isNotification() == false) {
            return;
        }

        Toast.makeText(this, text, Toast.LENGTH_LONG).show();
    }

}